
#include "fsmquickset.h"
#include <stdio.h>

// #define ALOGD   printf
namespace serial {

// header | length |   command   |   data   | check | tail
//  dd ff | 00 00  | C1 00 00 00 | ID ..... |   00  | bb cc
int FsmQuickset::onData(unsigned char data)
{
    // ALOGD("quickset: on data %#02x, now state: %d\n", data & 0xff, mState);

    if (mState == S_FF)
        chk = data;
    else
        chk ^= data;

    // ALOGD("checksum now is %02x\n", chk);

    switch (mState) {
    case S_INIT:
        return (data == 0xdd) ? changeState(S_DD) : fail("not dd");
    case S_DD:
        return (data == 0xff) ? changeState(S_FF) : fail("not ff");
    case S_FF:
        len = (int)(data << 8);
        return changeState(S_LEN1);
    case S_LEN1:
        len += (int)data;
        return (len > 5) ? changeState(S_LEN2) : fail("len < 6");
    case S_LEN2:
        return changeState(S_CMD1);
    case S_CMD1:
        return changeState(S_CMD2);
    case S_CMD2:
        return changeState(S_CMD3);
    case S_CMD3:
        return changeState(S_CMD4);
    case S_CMD4:
        return changeState(S_DATA);
    case S_DATA:
        len--;
        if (len == 5)
            return changeState(S_CHK);
        return 0;
    case S_CHK:
        return (data == 0xbb) ? changeState(S_BB) : fail("not bb");
    case S_BB:
        return (data == 0xcc) ? 1 : fail("not cc");
    case S_CC:
    default:
        return -1;
    }
    return 0;
}

void FsmQuickset::reset()
{
    mState = S_INIT;
    len = 0;
    chk = 0;
}

int FsmQuickset::fail(const char * reason)
{
    // ALOGD("not quickset: %s\n", reason);
    reset();
    return -1;
}

int FsmQuickset::changeState(State s)
{
    if (s == S_CHK) {
        if (chk != 0) {
            return fail("checksum failed.");
        }
    }
    mState = s;
    return 0;
}

} // namespace serial

